package com.cardone.common.util;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.List;

import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.reflect.FieldUtils;
import org.springframework.data.annotation.Id;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.ReflectionUtils.FieldCallback;
import org.springframework.util.ReflectionUtils.FieldFilter;

import com.cardone.common.annotation.BeginDate;
import com.cardone.common.annotation.EndDate;
import com.google.common.collect.Lists;

/**
 * 实体工具
 *
 * @author yaohaitao
 *
 */
public class EntityUtils {
	/**
	 * 添加：标识属性集合
	 *
	 * @param properties
	 *          属性集合
	 * @param o
	 *          对象
	 *
	 * @return 属性集合
	 */
	public static String[] addNotNullIdProperties(final String[] properties, final Object o) {
		final String[] notNullIdProperties = EntityUtils.getNotNullIdProperties(o);

		if (ArrayUtils.isEmpty(notNullIdProperties)) {
			return properties;
		}

		return ArrayUtils.addAll(properties, notNullIdProperties);
	}

	/**
	 * 添加：不为空值属性集合
	 *
	 * @param properties
	 *          属性集合
	 * @param o
	 *          对象
	 * @param annotationClassList
	 *          标注集合
	 *
	 * @return 不为空值属性集合
	 */
	public static String[] addNotNullProperties(final String[] properties, final Object o, final List<Class<? extends Annotation>> annotationClassList) {
		if (CollectionUtils.isEmpty(annotationClassList)) {
			return properties;
		}

		final String[] notNullProperties = EntityUtils.getNotNullProperties(o, annotationClassList);

		if (ArrayUtils.isEmpty(notNullProperties)) {
			return properties;
		}

		return ArrayUtils.addAll(properties, notNullProperties);
	}

	/**
	 * 添加：时间间隔属性集合
	 *
	 * @param properties
	 *          属性集合
	 * @param o
	 *          对象
	 *
	 * @return 属性集合
	 */
	public static String[] addNotNullTimeSegmentProperties(final String[] properties, final Object o) {
		final String[] notNullTimeSegmentProperties = EntityUtils.getNotNullTimeSegmentProperties(o);

		if (ArrayUtils.isEmpty(notNullTimeSegmentProperties)) {
			return properties;
		}

		return ArrayUtils.addAll(properties, notNullTimeSegmentProperties);
	}

	/**
	 * 获取：不为空值属性集合
	 *
	 * @param properties
	 *          属性集合
	 * @param o
	 *          不为空值属性集合
	 * @param idAnnotationClassList
	 *          标识标注集合
	 * @param timeSegmentAnnotationClassList
	 *          时间间隔标注集合
	 *
	 * @return 属性集合
	 */
	public static String[] addWhereProperties(final String[] properties, final Object o, final List<Class<? extends Annotation>> idAnnotationClassList, final List<Class<? extends Annotation>> timeSegmentAnnotationClassList) {
		String[] whereProperties = EntityUtils.getNotNullProperties(o, idAnnotationClassList);

		if (ArrayUtils.isNotEmpty(whereProperties)) {
			return whereProperties;
		}

		whereProperties = EntityUtils.getNotNullProperties(o, timeSegmentAnnotationClassList);

		if (ArrayUtils.isEmpty(whereProperties)) {
			return properties;
		}

		if (ArrayUtils.isEmpty(properties)) {
			return whereProperties;
		}

		return ArrayUtils.addAll(properties, whereProperties);
	}

	/**
	 * 添加：标识属性集合
	 *
	 * @param o
	 *          对象
	 *
	 * @return 属性集合
	 */
	public static String[] getNotNullIdProperties(final Object o) {
		final List<Class<? extends Annotation>> annotationClassList = Lists.newArrayList();

		annotationClassList.add(Id.class);

		return EntityUtils.getNotNullProperties(o, annotationClassList);
	}

	/**
	 * 获取：不为空值属性集合
	 *
	 * @param o
	 *          不为空值属性集合
	 * @param annotationClassList
	 *          标注集合
	 * @return 不为空值属性集合
	 */
	public static String[] getNotNullProperties(final Object o, final List<Class<? extends Annotation>> annotationClassList) {
		if (CollectionUtils.isEmpty(annotationClassList)) {
			return ArrayUtils.EMPTY_STRING_ARRAY;
		}

		final List<String> notNullPropertieList = Lists.newArrayList();

		ReflectionUtils.doWithFields(o.getClass(), new FieldCallback() {
			@Override
			public void doWith(final Field field) throws IllegalArgumentException, IllegalAccessException {
				final Object value = FieldUtils.readField(field, o, true);

				if (value != null) {
					notNullPropertieList.add(field.getName());
				}
			}
		}, new FieldFilter() {
			@Override
			public boolean matches(final Field field) {
				for (final Class<? extends Annotation> annotationClass : annotationClassList) {
					if (field.isAnnotationPresent(annotationClass)) {
						return true;
					}
				}

				return false;
			}
		});

		return notNullPropertieList.toArray(ArrayUtils.EMPTY_STRING_ARRAY);
	}

	/**
	 * 添加：时间间隔属性集合
	 *
	 * @param o
	 *          对象
	 *
	 * @return 属性集合
	 */
	public static String[] getNotNullTimeSegmentProperties(final Object o) {
		final List<Class<? extends Annotation>> annotationClassList = Lists.newArrayList();

		annotationClassList.add(BeginDate.class);
		annotationClassList.add(EndDate.class);

		return EntityUtils.getNotNullProperties(o, annotationClassList);
	}

	/**
	 * 获取：不为空值属性集合
	 *
	 * @param o
	 *          不为空值属性集合
	 * @param properties
	 *          属性集合
	 * @param idAnnotationClasss
	 *          标识标注集合
	 * @param timeSegmentAnnotationClasss
	 *          时间间隔标注集合
	 *
	 * @return 属性集合
	 */
	public static String[] getWhereProperties(final Object o, final String... properties) {
		final String[] whereProperties = EntityUtils.getNotNullIdProperties(o);

		if (ArrayUtils.isNotEmpty(whereProperties)) {
			return whereProperties;
		}

		return EntityUtils.addNotNullTimeSegmentProperties(properties, o);
	}
}